<?php
namespace Wj\Encipher\Symmetric;
class Openssl {

    private $aliase = "AES-256-ECB";
    private $option = OPENSSL_RAW_DATA;
    private $iv = "";
    private $tag = null;
    private $aad = "";
    private $tag_length = 16;
    protected $key = null;
    public function __construct(string $aliase = null, int $option = null, string $iv = null, string $tag = null, string $aad = null, int $tag_length = null) {
        if (!empty($aliase)) {
            if ($this->checkaliase($aliase)) {
                $this->aliase = $aliase;
            }
        }
        if (!empty($option)) {
            if ($this->checkoption($option)) {
                $this->option = $option;
            }
        }
        if (!empty($iv) && is_string($iv)) {
            $this->iv = $iv;
        }
    }
    public function checkaliase(string $aliase): bool {
        $list = openssl_get_cipher_methods(true);
        if (!in_array($aliase, $list)) {
            throw new \Throwable("aliase:" . $aliase . " is not supported by openssl");
        }
        return true;
    }
    public function checkoption(string $option): bool {
        $allow_arr = [OPENSSL_RAW_DATA, OPENSSL_ZERO_PADDING, OPENSSL_DONT_ZERO_PAD_KEY];
        if (!in_array($option, $allow_arr)) {
            throw new \Throwable("option:" . $option . " is not supported by openssl");
        }
        return true;
    }
    /**
     * 加密
     *
     * @param  [type] $data
     * @param  [type] $key
     * @param  [type] $aliase
     * @return void
     * @author wj
     * @date 2024-11-09
     */
    public function encrypt(string $plaintext, string $key = null): string {
        if (empty($key)) {
            if (empty($this->key)) {
                throw new \Throwable("key is empty");
            }
            $key = $this->key;
        }
        $ciphertext = openssl_encrypt($plaintext, $this->aliase, $key, $this->option, $this->iv);
        if (false === $ciphertext) {
            throw new \Throwable('Encrypting the input $plaintext failed, please checking your $key and $iv whether or nor correct.');
        }
        return base64_encode($ciphertext);
    }
    /**
     * 解密
     *
     * @param  [type] $data
     * @param  [type] $key
     * @param  [type] $aliase
     * @return void
     * @author wj
     * @date 2024-11-09
     */
    public function decrypt(string $ciphertext, string $key = null): string {
        if (empty($key)) {
            if (empty($this->key)) {
                throw new \Throwable("key is empty");
            }
            $key = $this->key;
        }
        $plaintext = openssl_decrypt(base64_decode($ciphertext), $this->aliase, $key, $this->option, $this->iv);
        if (false === $plaintext) {
            throw new \Throwable('Decrypting the input $ciphertext failed, please checking your $key and $iv whether or nor correct.');
        }
        return $plaintext;
    }

}